package com.house365.core.http;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.zip.GZIPInputStream;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.commons.logging.Log;

/**
 *@author Rick Ping
 *@date 2011-9-15
 *@comment Http connection utility class
 */
public class HttpURLConnectionUtil{
	//URL connection method
	public static  String CONNECTION_TYPE_POST="POST";
	public static  String CONNECTION_TYPE_GET="GET";
	public static String ENCODE="utf-8";
	
	public void setSSL(String keyStore,String trustStorePass){
		System.setProperty("javax.net.ssl.trustStore",keyStore);
		System.setProperty("javax.net.ssl.trustStorePassword",trustStorePass);
	}
	public String connectURL(String url,Map<String,Object> paramMap,String type) throws KeyManagementException, MalformedURLException, NoSuchAlgorithmException, NoSuchProviderException, IOException{
		return this.connectURL(url, paramMap, null,type);
	}
	/**
	 * open URL,and post data
	 * @param url
	 * @param paramMap
	 * @return
	 * @throws MalformedURLException
	 * @throws IOException
	 * @throws KeyManagementException 
	 * @throws NoSuchProviderException 
	 * @throws NoSuchAlgorithmException 
	 */
	public String connectURL(String url,Map<String,Object> paramMap,Map<String,String> head,String type) throws MalformedURLException, IOException, KeyManagementException, NoSuchAlgorithmException, NoSuchProviderException{
		
		StringBuffer sb=new StringBuffer();
		HttpURLConnection connection;
		if(type.equalsIgnoreCase(CONNECTION_TYPE_GET)){
			url =url +"?"+new String(prepareParam(paramMap).getBytes(ENCODE),ENCODE);
		}
		if("https".equalsIgnoreCase(url.substring(0, 5))){
			/**
			 * when use certification 
			 */
//			String keyStore = request.getRealPath(ScheduleConstant.CON_SYS_INIT_CONFIG.getString("Timer.KeyStore.SSLStorePath"));
//			String trustStorePass = ScheduleConstant.CON_SYS_INIT_CONFIG.getString("Timer.KeyStore.TrustStroePass");
//			String keyStore =request.getRealPath("/WEB-INF/security/i2.keystore");
//			String trustStorePass ="rick";
			//this.setSSL(keyStore, trustStorePass);
			HttpsURLConnection.setDefaultHostnameVerifier(ignoreHostnameVerifier);
			connection = (HttpsURLConnection)new URL(url).openConnection();
			
			/**
			 * ignore certification
			 */
			// Prepare SSL Context
            TrustManager[] tm = { ignoreCertificationTrustManger };
            SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
            sslContext.init(null, tm, new java.security.SecureRandom());

            // get SSLSocketFactory from above SSLContext
            SSLSocketFactory ssf = sslContext.getSocketFactory();
            ((HttpsURLConnection)connection).setSSLSocketFactory(ssf);
            
            
			
		}else{
			
			connection= (HttpURLConnection)new URL(url).openConnection();
		}
		if(type.equalsIgnoreCase(CONNECTION_TYPE_POST)){
			connection.setRequestMethod(CONNECTION_TYPE_POST);
		}
		
		if(head == null){
			head = new HashMap<String, String>();
		}
		setDefHead(head);
		for(Entry<String,String> entry : head.entrySet()){
			//connection.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
			connection.setRequestProperty(entry.getKey(),entry.getValue());
		}
		connection.setFollowRedirects(true);
		connection.setDoInput(true);
		connection.setDoOutput(true);
		connection.connect();
		if(type.equalsIgnoreCase(CONNECTION_TYPE_POST)){
			OutputStream out = connection.getOutputStream();
			out.write(this.prepareParam(paramMap).getBytes(ENCODE));
			out.flush();
			out.close();
		}
		BufferedReader in = this.getInputReader(connection);
		String line = "";
		while((line = in.readLine()) != null){
			sb.append(line);
		}
		in.close();
		//connection.
		return sb.toString();
		
	}
	private BufferedReader getInputReader(HttpURLConnection connection) throws UnsupportedEncodingException, IOException{
		String encoding = connection.getContentEncoding();
		BufferedReader reader = null;
		if(encoding == null || encoding.indexOf("gzip") == -1) {
			reader = new BufferedReader(new InputStreamReader(connection.getInputStream(),ENCODE));
		}else{
			reader = new BufferedReader(new InputStreamReader(new GZIPInputStream(connection.getInputStream()),ENCODE));
		}
		return reader;
	}
	private void setDefHead(Map<String,String> head){
		
		if(!head.containsKey("Content-Type")){
			head.put("Content-Type","application/x-www-form-urlencoded");
		}
	}
	/**
	 * generate params
	 * @param paramMap
	 * @return
	 * @throws UnsupportedEncodingException 
	 */
	private String prepareParam(Map<String,Object> paramMap) throws UnsupportedEncodingException{
		StringBuffer sb = new StringBuffer();
		if(paramMap== null || paramMap.isEmpty()){
			return "";
		}else{
			Set<Entry<String,Object>> set = paramMap.entrySet();
			for(Entry<String,Object> entry:set){
				String key = URLEncoder.encode(entry.getKey(),ENCODE);
				String value = URLEncoder.encode(entry.getValue().toString(),ENCODE);
				if(sb.length()>=1){
					sb.append("&");
				}
				sb.append(key).append("=").append(value);
			}
		}
		return sb.toString();
	}
	/**
	 * ignore HostName
	 */
	private static  HostnameVerifier ignoreHostnameVerifier = new HostnameVerifier() {
		
		public boolean verify(String hostname, SSLSession session) {
			return true;
		}
	};;;
	
	


     /**
     * Ignore Certification
     */
    private  static TrustManager ignoreCertificationTrustManger = new X509TrustManager() {

        private X509Certificate[] certificates;

     
        public void checkClientTrusted(X509Certificate certificates[],
                String authType) throws CertificateException {
            if (this.certificates == null) {
                this.certificates = certificates;
                System.out.println("init at checkClientTrusted");
            }

        }

        
        public void checkServerTrusted(X509Certificate[] ax509certificate,
                String s) throws CertificateException {
            if (this.certificates == null) {
                this.certificates = ax509certificate;
                System.out.println("init at checkServerTrusted");
            }

//            for (int c = 0; c < certificates.length; c++) {
//                X509Certificate cert = certificates[c];
//                System.out.println(" Server certificate " + (c + 1) + ":");
//                System.out.println("  Subject DN: " + cert.getSubjectDN());
//                System.out.println("  Signature Algorithm: "
//                        + cert.getSigAlgName());
//                System.out.println("  Valid from: " + cert.getNotBefore());
//                System.out.println("  Valid until: " + cert.getNotAfter());
//                System.out.println("  Issuer: " + cert.getIssuerDN());
//            }

        }

        public X509Certificate[] getAcceptedIssuers() {
            // TODO Auto-generated method stub
            return null;
        }

    };

}
